package Domain.UserClient;


import Domain.DataManager;

import java.io.IOException;
import java.util.Vector;


import objects.*;
import Domain.stompProtocol.StompClient;
import Domain.stompProtocol.StompFrame;

import com.thoughtworks.xstream.XStream;

public class SocketListener implements Runnable{

	private XStream _xstream;
	private DataManager _dm;
	private StompClient _stoClient;

	/**
	 * constructor
	 * @param _socket the socket of the server
	 * @param printer the print writer
	 */
	public SocketListener(ButtonsFunctions bf, DataManager dm, StompClient stoCli)
	{
		this._xstream = new XStream();
		_xstream.alias("ForumFrame", ForumFrame.class);

		this._dm = dm;
		this._stoClient = stoCli;
	}

	public void run() 
	{
		while(true)
		{
			try {
				processMessage(this._stoClient.getStompFrame());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * process the message received from the server
	 * @param msg the message received
	 */

	public void processMessage(StompFrame sFrame)
	{   
		int sFrameType = sFrame.getMsgType(); 
		
		if (sFrameType == StompFrame.MSGREGISTERED)
		{
			processRegistered();
		}
		else if(sFrameType == StompFrame.MSGCONNECTED)
		{
			processConnected();
		}
		else if(sFrameType == StompFrame.MSGERROR)
		{
			processError(sFrame.toString());
		}
		else if(sFrameType==StompFrame.MSGANSISAVAILABLE){
			processAvailabilityCheck(sFrame.getData());
		}
		else if(sFrameType == StompFrame.MSGSEND)
		{
			try
			{
				ForumFrame fFrame = (ForumFrame)(_xstream.fromXML(sFrame.getData()));	
			
				int type = fFrame.getType();
				if(type == ForumFrame.VECTORFRM)
					processVectorFrm(fFrame);
				else if(type == ForumFrame.TYPESECCESS)
					processSuccess(fFrame);			//need to check which messages return success
					else if(type == ForumFrame.TYPETHREAD)
						processThread(fFrame);
					else if(type == ForumFrame.VECTORTRD)
						processVectorTrd(fFrame);
					else if(type == ForumFrame.VECTORUSER)
						processVectorUser(fFrame);
					else if(type == ForumFrame.VECTORMSG)
						processVectorMsg(fFrame);
					else if(type == ForumFrame.VECTORFRIENDS)
						processVectorFriends(fFrame);
					else if(type == ForumFrame.TYPEDefaultUser | type == ForumFrame.TYPEManager)
						processUserType(fFrame);
					else if(type == ForumFrame.TYPEFriendPublishMsg)
						processFriendPublishMsg(fFrame);
					else if(type == ForumFrame.TYPEUserPublishMsg)
						processUserPublishedMessage(fFrame);
					else if(type < 0)
						processError(fFrame);
					else
						System.out.println(sFrame);
			}
			catch(Exception e)
			{
				System.out.println("MY EXCEPTION:");
				e.printStackTrace();
			}
		}
		else				//MGGERROR or error in the type of StompFrame
		{
			System.out.println("Error in type of StompFrame, the message recieved was:\n" + sFrame);
		}
	}



	private void processError(ForumFrame fFrame) 
	{
		System.out.println("An Error of type " +fFrame.type + " have been recieved.");
		this._dm.addError("An Error of type " +fFrame.type + " have been recieved.");
	}

	private void processVectorMsg(ForumFrame fFrame) 
	{
		try
		{
			@SuppressWarnings("unchecked")
			Vector<Message> messages = (Vector<Message>)fFrame.getData();
			this._dm.setVerctorMesseges(messages);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	private void processVectorUser(ForumFrame fFrame) 
	{
		try
		{
			@SuppressWarnings("unchecked")
			Vector<User> users = (Vector<User>)fFrame.getData();
			this._dm.setVectorOfUsers(users);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	private void processVectorTrd(ForumFrame fFrame) 
	{
		try
		{
			@SuppressWarnings("unchecked")
			Vector<Trd> trds = (Vector<Trd>)fFrame.getData();
			this._dm.setVerctorThreads(trds);
			//                     
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	private void processThread(ForumFrame fFrame) 
	{
		System.out.println("ASAF SENT US A SINGLE THREAD!!!");
	}

	private void processSuccess(ForumFrame fFrame) 
	{
		this._dm.setSuccessOrFailure(DataManager.SUCCESS);
	}

	private void processVectorFrm(ForumFrame fFrame)
	{
		try
		{
			@SuppressWarnings("unchecked")
			Vector<Frm> forums = (Vector<Frm>)fFrame.getData();
			this._dm.setVectorForums(forums);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}


	private void processRegistered() {
		this._dm.setRegisteredTrue();
	}

	private void processConnected()
	{
		this._dm.setConnectedTrue();
	}

	private void processError(String error)
	{
		this._dm.setSuccessOrFailure(DataManager.FAILURE);
		System.out.println("Error retrieved from the server (it's OK): \n" + error);
	}

	private void processUserType(ForumFrame fFrame)
	{
		int type;
		if(fFrame.getType() == ForumFrame.TYPEDefaultUser)
			type = 0;
		else if (fFrame.getType() == ForumFrame.TYPEManager){
			type = 1;
		}
		else
		{
			type = -1;
			return;
		}
		this._dm.setTypeOfUser(type);
	}

	private void processAvailabilityCheck(String ans){
		if(ans.equals("yes"))
		{
			this._dm.setAvailable(true);
		}
		else// if(ans.equals("no"))
		{
			this._dm.setAvailable(false);
		}
	}

	private void processVectorFriends(ForumFrame fFrame) {
		try
		{
			@SuppressWarnings("unchecked")
			Vector<User> friends = (Vector<User>)fFrame.getData();
			this._dm.setVerctorFriends(friends);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

    private void processFriendPublishMsg(ForumFrame fFrame) {
        String str = (String)fFrame.getData();
        char delimiter = ';';
        int index = str.indexOf(delimiter)+1;
        int indexend = str.indexOf(delimiter, index);
        if(indexend == -1)
                indexend = str.length();
        String user = str.substring(0, index-1);
        String forum = str.substring(index,indexend).trim();
        String thread = str.substring(indexend+1,str.lastIndexOf(delimiter));
        String postTitle = str.substring(str.lastIndexOf(delimiter)+1);
        this._dm.addNotification ( "Your friend \""+user +  "\" added\\edited the post \""+postTitle+"\" in thread \"" +thread + "\", forum \""+forum+"\".");
    }

    private void processUserPublishedMessage(ForumFrame fFrame) {
        String str = (String)fFrame.getData();
        char delimiter = ';';
        int index = str.indexOf(delimiter)+1;
        int indexend = str.indexOf(delimiter, index);
        if(indexend == -1)
                indexend = str.length();
        String user = str.substring(0, index-1);
        String forum = str.substring(index,indexend).trim();
        String thread = str.substring(indexend+1,str.lastIndexOf(delimiter));

         String currUser = this._dm.getCurrUser();

        if(forum.equals(this._dm.getCurrForum()) && !user.equals(currUser))
        	this._dm.addNotification("A new message has been added\\edited in thread \"" +thread + "\", forum \""+forum+"\".");
    }



}
